<template>
   <el-form label-width="150px" :model="spuInfo" :rules="rules" ref="formRef">
    <el-form-item label="SPU名称" prop="spuName">
      <el-input 
      type="text" 
      placeholder="SPU名称"  
      v-model="spuInfo.spuName">
    </el-input>
    </el-form-item>
    <el-form-item label="品牌"  prop="tmId">
      <el-select 
      v-model="spuInfo.tmId">
        <el-option 
        v-for="tm in trademarkList" 
        :label="tm.tmName" 
        :value="tm.id as number" 
        :key="tm.id">
        </el-option>
      </el-select>
    </el-form-item>
    <el-form-item label="SPU描述" prop="description">
      <el-input 
      type="textarea" 
      placeholder="SPU描述" 
      v-model="spuInfo.description">
    </el-input>
    </el-form-item>

    <el-form-item label="SPU图片" prop="spuImageList">
      <!-- multiple: 图片可以多选属性 -->
      <el-upload
        multiple 
        v-model:file-list="spuInfo.spuImageList as any"
        :action="`${BASE_UPLOAD}/admin/product/fileUpload`"
        list-type="picture-card"
        :on-preview="handlePictureCardPreview"
        :on-remove="handleRemove"
        :on-success="handleSuccess"
      >
        <el-icon><Plus /></el-icon>
      </el-upload>

      <el-dialog v-model="dialogVisible">
        <img w-full :src="dialogImageUrl" alt="Preview Image" />
      </el-dialog>
    </el-form-item>

    <el-form-item label="SPU销售属性" prop="spuSaleAttrList">
      <div>
        <el-select 
        :placeholder="selectText" 
        v-model="valueIdValueName">
          <el-option 
          :label="attr.name" 
          :value="attr.id + ':'+attr.name" 
          v-for="attr in restSaleAttrList" 
          :key="attr.id"></el-option>
        </el-select>
        <el-button 
        type="primary" 
        :icon="Plus"
        :disabled="!valueIdValueName"
        @click="addSpuSaleAttr"
        >添加属性值</el-button>
      </div>

      <el-table :data="spuInfo.spuSaleAttrList" style="margin-top: 10px;">
        <el-table-column 
        label="序号" 
        type="index" 
        width="80px" 
        align="center"></el-table-column>
        <el-table-column label="属性名" prop="saleAttrName"></el-table-column>
        <el-table-column label="属性值名称列表">
          <template v-slot="{row}">
            <el-tag 
            closable 
            v-for="(value,index) in row.spuSaleAttrValueList" :key="value.id"
            @close="row.spuSaleAttrValueList.splice(index, 1)"
            >{{ value.saleAttrValueName }}</el-tag>
            <el-input
             v-if="row.isEdit" style="width: 100px;" 
            @blur="toShow(row)" 
            ref="inputRef" 
            v-model="valueName" 
            placeholder="名称"></el-input>
            <el-button v-else size="small" :icon="Plus" @click="toEdit(row)"></el-button>
          </template>
        </el-table-column>
        <el-table-column label="操作">
          <template v-slot="{ $index }">
            <el-button
              type="danger"
              :icon="Delete"
              @click="spuInfo.spuSaleAttrList.splice($index, 1)"
            ></el-button>
          </template>
        </el-table-column>
      </el-table>
    </el-form-item>

    <el-form-item>
      <el-button type="primary" @click="save" :loading="saveLoading">保存</el-button>
      <el-button @click="$emit('setShowStatus', ShowStatus.SPU_LIST)">取消</el-button>
    </el-form-item>
  </el-form>
</template>

<script lang="ts">
  export default  defineComponent({
    name:'SpuForm'
  })
</script>
<script lang="ts" setup>
 import { defineComponent } from 'vue'
import type { BaseSaleAttrListModel, SpuModel, SpuSaleAttrModel } from '@/api/product/model/spuModel';
import type { TrademarksModel } from '@/api/product/model/trademarkModel';
import { getAllTrademarkListApi } from '@/api/product/trademark';
import { addOrUpdateSpuApi, getBaseSaleAttrListApi, getSpuImageListApi, getSpuSaleAttrListApi } from '@/api/product/spu';
import { computed, nextTick, onMounted, reactive, ref } from 'vue'
import { ElMessage, type FormInstance, type FormRules, type InputInstance, type UploadProps } from 'element-plus';
import { Delete, Plus } from '@element-plus/icons-vue';
import  { ShowStatus } from '../types';
import { cloneDeep } from 'lodash';

// 声明接收props
const props = defineProps<{
  spu: SpuModel
}>()

const saveLoading = ref(false)

// 声明一个用于收集spu表单数据的spu详情信息对象
const spuInfo = reactive<SpuModel>(props.spu)

  // 声明定义自定义事件, 返回的是分发事件的函数
const emit = defineEmits<{
  (e: 'setShowStatus', value: ShowStatus): void
}>()

/* 
请求添加或修改spu
*/
const save = async () => {
  // 先校验
  // formRef.value?.validate((valid) => {
  //   if (valid) {
  //     alert('准备请求...')
  //   }
  // })
  // 校验的返回值是一个promise, 校验成功promise就会成功
  await formRef.value?.validate()
  // 在发请求对spuInfo进行数据整理/处理

  // 对spuInfo产生一个拷贝对象
  const cloneSpuInfo = cloneDeep(spuInfo)


  /* 1. 处理spuImage的结构
	目标结构:
		{
      "imgName": "下载 (1).jpg",
      "imgUrl": "http://47.93.148.192:8080/xxx.jpg"
    }
  当前的结构:
  	原本就有的图片
  	{
  		name: '图片文件名'
  		imgUrl: '图片url'
  	}
  	// 原本就有的图片
  	{
  		name: '图片文件名',
  		response: {data: '图片url'}   // 新上传的图片
  	}
  	
  	需要在数据类型添加: response的结构
  	给name的值添加为imgName属性
  	将imgUrl或response.data的值给imgUrl */
    cloneSpuInfo.spuImageList = cloneSpuInfo.spuImageList.map(item => ({
    imgName: item.name!,
    imgUrl: item.response ? item.response.data : item.imgUrl
  }))

    /* 2. 处理 spuSaleAttr对象
		删除isEdit属性
		过滤掉没有属性值名称的属性对象 */
  cloneSpuInfo.spuSaleAttrList = cloneSpuInfo.spuSaleAttrList.filter(item => {
    // 如果有属性值, 就留下来
    if (item.spuSaleAttrValueList.length>0) {
      // 删除isEdit属性
      delete item.isEdit
      return true
    }

    return false
  })

  // 显示loading 
  saveLoading.value = true

  try {
    // 发送添加/更新的请求: addOrUpdateSpuApi
    await addOrUpdateSpuApi(cloneSpuInfo)
    // 请求成功后: 提示 / 显示列表页面
    ElMessage.success('保存成功!')
    emit('setShowStatus', ShowStatus.SPU_LIST)
    // 隐藏loading
    // saveLoading.value = false
  } catch (error) {
    // 隐藏loading
    // saveLoading.value = false
  } finally { // 请求成功或失败都要隐藏loading
    saveLoading.value = false
  }
}


/* **表单校验 start** */
const formRef = ref<FormInstance>()
const rules: FormRules = {
  spuName: [{required: true, message: 'spu名称是必须的', trigger: 'blur'}],
  tmId: [{required: true, message: '品牌是必须的'}],
  description: [{required: true, message: '描述是必须的'}],
  spuImageList: [{required: true, message: '必须上传spu图片', type:'array'}],
  spuSaleAttrList: [{required: true, message: '必须指定spu销售属性', type:'array'}],
}
/* **表单校验 end** */


/* **spu销售属性处理 start** */
const inputRef = ref<InputInstance>()
const valueName = ref('')  // 保存输入的属性值名称
// 切换为查看模式
const toShow = (row: SpuSaleAttrModel) => {

  // 只有输入了值且不重复才去添加
  if (valueName.value) {
    // 判断是否不重复
    const notRepeat = row.spuSaleAttrValueList.every(item => item.saleAttrValueName!==valueName.value)
    if (notRepeat) {
      // 创建一个属性值对象
      const attrValu = {
        saleAttrValueName: valueName.value,
        baseSaleAttrId: row.baseSaleAttrId
      }
      // 添加到属性值列表中
      row.spuSaleAttrValueList.push(attrValu)
    }
  }
  // 变为查看模式
  row.isEdit = false
  // 清除收集的输入数据
  valueName.value = ''
}
// 切换为编辑模式
const toEdit = (row: SpuSaleAttrModel) => {
  // isEdit变为true, 
  row.isEdit = true
  // 自动获得焦点
  nextTick(() => {
    inputRef.value?.focus()
  })
}
/* **spu销售属性处理 end** */

/* 初始化请求 start */
// 所有品牌的列表
const trademarkList = ref<TrademarksModel>([])
// 所有销售属性的列表
const saleAttrList = ref<BaseSaleAttrListModel>([])
// 收集选择销售属性的id和name   id:name
const valueIdValueName = ref('');

// 点击添加一个新的spu销售属性
const addSpuSaleAttr = () => {
  // 对valueIdValueName进行拆分, 得到 id和name
  const [id, name] = valueIdValueName.value.split(':')
  // 创建一个新的spu销售属性对象, 并添加到对应的列表中
  spuInfo.spuSaleAttrList.push({
    baseSaleAttrId: +id,
    saleAttrName: name,
    spuSaleAttrValueList: [],
  });
  // 清除选择收集的valueIdValueName
  valueIdValueName.value = ''
};


// 剩余可选的销售属性列表
const restSaleAttrList = computed(()=>{
  return saleAttrList.value.filter(attr=>{
    // attr.name 在spuInfo.spuSaleAttrList中有没有对应的
    return !spuInfo.spuSaleAttrList.some(saleAttr=>saleAttr.saleAttrName===attr.name)
  })
})

// 计算出下拉列表的提示文本
const selectText = computed(()=>{
  const length = restSaleAttrList.value.length
  return length === 0 ?'没有啦！' : `还有${length}个可选的`
})
/* 
1. 获取所有品牌列表 trademark.getAllTrademarkListApi()  trademarkList
2. 获取基础销售属性列表  spu.getBaseSaleAttrListApi()  saleAttrList
3. 获取spu图片列表   spu.getSpuImageListApi(spuId)  spuInfo.spuImageList
4. 获取spu销售属性列表  spu.getSpuSaleAttrListApi(spuId)  spuInfo.spuSaleAttrList
*/
onMounted( async () => {
  trademarkList.value = await getAllTrademarkListApi()
})
onMounted( async () => {
  saleAttrList.value = await getBaseSaleAttrListApi()
})
onMounted( async () => {
  // 如果没有spuId, 不发请求
  if (!spuInfo.id) return;

  const spuImageList = await getSpuImageListApi(spuInfo.id!); // 此时!可以不写, 因为前面有判断
  // 使用forEach
  // spuImageList.forEach(item => {
  //   item.name = item.imgName
  //   item.url = item.imgUrl
  // })

  /* 
  通用问题: 请求得到的数据结构不能满足显示的需求
	Upload组件需要的图片对象{name, url}
	而我们的数据在{imgName, imgUrl}
  解决: 当请求得到数据后, 对数据进行整理
      将imgName值给name属性, 将imgUrl的值给url属性
  */
  spuInfo.spuImageList = spuImageList.map(item => ({
    ...item,
    name: item.imgName,
    url: item.imgUrl
  }))
})
onMounted(async () => {
// 如果没有spuId, 不发请求
if (!spuInfo.id) return;

const spuSaleAttrList = await getSpuSaleAttrListApi(spuInfo.id as number);
spuInfo.spuSaleAttrList = spuSaleAttrList;
});

/* 初始化请求 end */


/* 图片上传处理 start */
const BASE_UPLOAD = import.meta.env.VITE_BASE_URL //代理的基础路径
// 大图url
const dialogImageUrl = ref('')
// 是否显示大图
const dialogVisible = ref(false)

// 点击删除回调
// uploadFile: 要删除的图片对象
// uploadFiles: 剩余的图片列表
const handleRemove: UploadProps['onRemove'] = (uploadFile, uploadFiles) => {
  // console.log(uploadFile, uploadFiles)
  spuInfo.spuImageList = uploadFiles as any  //数据等到发请求前进行整理
}


// 点击放大镜的回调
// uploadFile: 点击的图片对象
const handlePictureCardPreview: UploadProps['onPreview'] = (uploadFile) => {
   // 指定要显示的大图url
  dialogImageUrl.value = uploadFile.url!

    // 显示dialog
  dialogVisible.value = true
}
// 上传成功的回调
// response: 上传请求的响应体数据  {data: 图片的url}
// uploadFile: 上传成功的图片对象
// uploadFiles: 已上传的图片列表
const handleSuccess:UploadProps['onSuccess'] = (response, uploadFile, uploadFiles) => {
  console.log('onSuccess', uploadFiles)
  spuInfo.spuImageList = uploadFiles as any  // 数据等到发请求前进行整理

   // 在上传图片成功后, 手动清除错误信息
   formRef.value?.clearValidate(['spuImageList'])
} 
/* 图片上传处理 end */
</script>

<style lang="scss" scoped>
  
</style>